home *** CD-ROM | disk | FTP | other *** search
/ Personal Computer World 2009 February / PCWFEB09.iso / Software / Resources / Browsers, Managers & Extensions / Mozilla Weave 0.2.7 / latest-weave.xpi / chrome / sync.jar / content / wizard.js < prev    next >
Text File  |  2008-10-15  |  51KB  |  1,297 lines

  1. /* ***** BEGIN LICENSE BLOCK *****
  2.  * Version: MPL 1.1/GPL 2.0/LGPL 2.1
  3.  *
  4.  * The contents of this file are subject to the Mozilla Public License Version
  5.  * 1.1 (the "License"); you may not use this file except in compliance with
  6.  * the License. You may obtain a copy of the License at
  7.  * http://www.mozilla.org/MPL/
  8.  *
  9.  * Software distributed under the License is distributed on an "AS IS" basis,
  10.  * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
  11.  * for the specific language governing rights and limitations under the
  12.  * License.
  13.  *
  14.  * The Original Code is Bookmarks Sync.
  15.  *
  16.  * The Initial Developer of the Original Code is Mozilla.
  17.  * Portions created by the Initial Developer are Copyright (C) 2007
  18.  * the Initial Developer. All Rights Reserved.
  19.  *
  20.  * Contributor(s):
  21.  *  Dan Mills <thunder@mozilla.com>
  22.  *  Chris Beard <cbeard@mozilla.com>
  23.  *  Maria Emerson <memerson@mozilla.com>
  24.  *
  25.  * Alternatively, the contents of this file may be used under the terms of
  26.  * either the GNU General Public License Version 2 or later (the "GPL"), or
  27.  * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
  28.  * in which case the provisions of the GPL or the LGPL are applicable instead
  29.  * of those above. If you wish to allow use of your version of this file only
  30.  * under the terms of either the GPL or the LGPL, and not to allow others to
  31.  * use your version of this file under the terms of the MPL, indicate your
  32.  * decision by deleting the provisions above and replace them with the notice
  33.  * and other provisions required by the GPL or the LGPL. If you do not delete
  34.  * the provisions above, a recipient may use your version of this file under
  35.  * the terms of any one of the MPL, the GPL or the LGPL.
  36.  *
  37.  * ***** END LICENSE BLOCK ***** */
  38.  
  39. const SYNC_NS_ERROR_LOGIN_ALREADY_EXISTS = 2153185310;
  40.  
  41. const REGISTER_STATUS    = "api/register/regopen/";
  42. const REGISTER_URL       = "api/register/new/";
  43. const CHECK_USERNAME_URL = "api/register/check/";
  44. const CHECK_EMAIL_URL    = "api/register/chkmail/";
  45. const CAPTCHA_IMAGE_URL  = "http://api.recaptcha.net/image";
  46.  
  47. const PROGRESS_COLOR     = "black";
  48. const ERROR_COLOR        = "red";
  49. const SERVER_ERROR_COLOR = "black";
  50. const SUCCESS_COLOR      = "blue";
  51.  
  52. const SERVER_TIMEOUT = 15000;
  53.  
  54. var Cc = Components.classes;
  55. var Ci = Components.interfaces;
  56.  
  57. function SyncWizard() {
  58.   this._init();
  59. }
  60.  
  61. SyncWizard.prototype = {
  62.  
  63.   registrationClosed: false,
  64.  
  65.   __os: null,
  66.   get _os() {
  67.     if (!this.__os)
  68.       this.__os = Cc["@mozilla.org/observer-service;1"]
  69.                   .getService(Ci.nsIObserverService);
  70.     return this.__os;
  71.   },
  72.  
  73.   get _stringBundle() {
  74.     let stringBundle = document.getElementById("weaveStringBundle");
  75.     this.__defineGetter__("_stringBundle",
  76.                           function() { return stringBundle; });
  77.     return this._stringBundle;
  78.   },
  79.  
  80.   _init : function SyncWizard__init() {
  81.     let branch = Cc["@mozilla.org/preferences-service;1"].
  82.                      getService(Ci.nsIPrefService).getBranch(Weave.PREFS_BRANCH);
  83.  
  84.     this._serverURL = branch.getCharPref("serverURL");
  85.  
  86.     this._log = Log4Moz.Service.getLogger("Chrome.Wizard");
  87.  
  88.     if (Weave.Service.isLoggedIn) {
  89.       Weave.Service.logout();
  90.     }
  91.  
  92.     this._log.info("Initializing setup wizard");
  93.  
  94.     this._os.addObserver(this, "weave:service:login:success", false);
  95.     this._os.addObserver(this, "weave:service:login:error", false);
  96.     this._os.addObserver(this, "weave:service:verify-login:success", false);
  97.     this._os.addObserver(this, "weave:service:verify-login:error", false);
  98.     this._os.addObserver(this, "weave:service:verify-passphrase:success", false);
  99.     this._os.addObserver(this, "weave:service:verify-passphrase:error", false);
  100.     this._os.addObserver(this, "weave:service:logout:success", false);
  101.     this._os.addObserver(this, "weave:service:sync:start", false);
  102.     this._os.addObserver(this, "weave:service:sync:success", false);
  103.     this._os.addObserver(this, "weave:service:sync:error", false);
  104.  
  105.     // Initial background request to check if registration is open or closed.
  106.     // this.checkRegistrationStatus();
  107.   },
  108.  
  109.   onWizardShutdown: function SyncWizard_onWizardshutdown() {
  110.     this._log.info("Shutting down setup wizard");
  111.  
  112.     this._os.removeObserver(this, "weave:service:login:success");
  113.     this._os.removeObserver(this, "weave:service:login:error");
  114.     this._os.removeObserver(this, "weave:service:verify-login:success");
  115.     this._os.removeObserver(this, "weave:service:verify-login:error");
  116.     this._os.removeObserver(this, "weave:service:verify-passphrase:success", false);
  117.     this._os.removeObserver(this, "weave:service:verify-passphrase:error", false);
  118.     this._os.removeObserver(this, "weave:service:logout:success");
  119.     this._os.removeObserver(this, "weave:service:sync:start");
  120.     this._os.removeObserver(this, "weave:service:sync:success");
  121.     this._os.removeObserver(this, "weave:service:sync:error");
  122.   },
  123.  
  124.  
  125.   onPageShow: function SyncWizard_onPageShow(pageId) {
  126.     let wizard = document.getElementById('sync-wizard');
  127.  
  128.     switch(pageId) {
  129.       case "sync-wizard-intro":
  130.         let radio = document.getElementById("acceptOrDecline");
  131.         radio.value = "false";
  132.         wizard.canAdvance = false;
  133.         break;
  134.  
  135.       case "sync-wizard-welcome":
  136.         wizard.canAdvance = false;
  137.         break;
  138.  
  139.       case "sync-wizard-verify":
  140.         if (document.getElementById("verify-check").value == "true")
  141.           wizard.canAdvance = true;
  142.         else
  143.           wizard.canAdvance = false;
  144.         break;
  145.  
  146.       case "sync-wizard-create1":
  147.  
  148.         // Check to see if registration is closed, and if so display a friendly message
  149.         // to the would be user and then push them back to the registration menu.
  150.         if (this.registrationClosed) {
  151.             let p = Cc["@mozilla.org/embedcomp/prompt-service;1"]
  152.                       .getService(Ci.nsIPromptService);
  153.             p.alert(null,this._stringBundle.getString("registration-closed.title"),
  154.                       this._stringBundle.getString("registration-closed.label"));
  155.             wizard.goTo("sync-wizard-welcome");
  156.         }
  157.  
  158.         if (document.getElementById("create1-check").value == "true")
  159.           wizard.canAdvance = true;
  160.         else
  161.           wizard.canAdvance = false;
  162.         break;
  163.  
  164.       case "sync-wizard-create2":
  165.         if (document.getElementById("create2-check").value == "true")
  166.           wizard.canAdvance = true;
  167.         else
  168.           wizard.canAdvance = false;
  169.         break;
  170.  
  171.       case "sync-wizard-create3":
  172.         if (document.getElementById("create3-check").value == "true") {
  173.           //document.getElementById("captchaInput").value = "";
  174.           wizard.canAdvance = true;
  175.         }
  176.         else {
  177.           document.getElementById("captcha").addEventListener("pageshow", function() {gSyncWizard.onLoadCaptcha()}, false, true);
  178.           document.getElementById("captcha").setAttribute("src", this._serverURL + REGISTER_URL);
  179.           wizard.canAdvance = false;
  180.         }
  181.         break;
  182.  
  183.       case "sync-wizard-data": {
  184.         let deviceName = document.getElementById('sync-instanceName-field');
  185.         let deviceType = document.getElementById('sync-instanceType-field');
  186.         let path = document.getElementById('path').value;
  187.         let username;
  188.  
  189.         if (path == "verify")
  190.           username = document.getElementById('sync-username-field').value;
  191.         else if (path == "create")
  192.           username = document.getElementById('sync-username-create-field').value;
  193.  
  194.         let branch = Cc["@mozilla.org/preferences-service;1"].
  195.                      getService(Ci.nsIPrefService).getBranch(Weave.PREFS_BRANCH + "engine.");
  196.         // TODO: Move this into a separate module for use in prefs and wizard
  197.         document.getElementById('sync-wizard-bookmarks').checked = branch.getBoolPref("bookmarks");
  198.         document.getElementById('sync-wizard-history').checked = branch.getBoolPref("history");
  199.         document.getElementById('sync-wizard-cookies').checked = branch.getBoolPref("cookies");
  200.         document.getElementById('sync-wizard-passwords').checked = branch.getBoolPref("passwords");
  201.         document.getElementById('sync-wizard-tabs').checked = branch.getBoolPref("tabs");
  202.         document.getElementById('sync-wizard-forms').checked = branch.getBoolPref("forms");
  203.  
  204.     if(deviceName) 
  205.           branch.setCharPref("client.name", deviceName);
  206.  
  207.         if(deviceType)
  208.           branch.setCharPref("client.type", deviceType);
  209.  
  210.         wizard.canAdvance = true;
  211.         break;
  212.       }
  213.       case "sync-wizard-final": {
  214.         // display the username
  215.         let accountDetails = document.getElementById('final-account-details');
  216.         let path = document.getElementById('path').value;
  217.         let username;
  218.  
  219.         if (path == "verify")
  220.           username = document.getElementById('sync-username-field').value;
  221.         else if (path == "create")
  222.           username = document.getElementById('sync-username-create-field').value;
  223.         accountDetails.value = this._stringBundle.getFormattedString("final-account-value.label", [username]);
  224.  
  225.         // get the preferences
  226.         var prefArray = new Array();
  227.         if (document.getElementById('sync-wizard-bookmarks').checked)
  228.           prefArray.push(this._stringBundle.getString("bookmarks.label"));
  229.         if (document.getElementById('sync-wizard-history').checked)
  230.           prefArray.push(this._stringBundle.getString("history.label"));
  231.         if (document.getElementById('sync-wizard-cookies').checked)
  232.           prefArray.push(this._stringBundle.getString("cookies.label"));
  233.         if (document.getElementById('sync-wizard-passwords').checked)
  234.           prefArray.push(this._stringBundle.getString("passwords.label"));
  235.         if (document.getElementById('sync-wizard-tabs').checked)
  236.           prefArray.push(this._stringBundle.getString("tabs.label"));
  237.         if (document.getElementById('sync-wizard-forms').checked)
  238.           prefArray.push(this._stringBundle.getString("formdata.label"));
  239.         var prefString = "";
  240.         for (var i=0; i<prefArray.length-1; i++)
  241.           prefString = prefString + prefArray[i] + ", ";
  242.           prefString = prefString + prefArray[prefArray.length-1];
  243.  
  244.         // display the preferences
  245.         let prefDetails = document.getElementById('final-pref-details');
  246.         prefDetails.value = prefString;
  247.  
  248.         // explain sync
  249.         let syncDetails = document.getElementById('final-sync-details');
  250.         syncDetails.value = this._stringBundle.getString("final-sync-value.label");
  251.  
  252.         if (document.getElementById("sync-success").value == "true")
  253.           wizard.canAdvance = true;
  254.         else if (document.getElementById("installation-started").value == "false")
  255.           wizard.canAdvance = true;
  256.         else
  257.           wizard.canAdvance = false;
  258.         break;
  259.       }
  260.       default:
  261.         this._log.warn("Unknown wizard page requested: " + pageId);
  262.         break;
  263.     }
  264.   },
  265.  
  266.   /////INTRO SCREEN/////
  267.  
  268.   onChangeTermsRadio: function SyncWizard_onChangeEULARadio() {
  269.     let wizard = document.getElementById('sync-wizard');
  270.     let radio = document.getElementById("acceptOrDecline");
  271.  
  272.     wizard.canAdvance = (radio.value == "true");
  273.   },
  274.  
  275.  
  276.   /////WELCOME SCREEN/////
  277.  
  278.  
  279.   /* setTitles() - Called by welcome screen to set upcoming page titles.
  280.    */
  281.   setTitles: function SyncWizard_setTitles(type) {
  282.     let wizard = document.getElementById('sync-wizard');
  283.     let dataPage  = wizard.getPageById('sync-wizard-data');
  284.     let finalPage = wizard.getPageById('sync-wizard-final');
  285.  
  286.     // The hidden "path" label- for later use so we know which path the user took.
  287.     let path = document.getElementById('path');
  288.  
  289.     if (type == "verify") {
  290.       dataPage.setAttribute("label", this._stringBundle.getString("data-verify.title"));
  291.       finalPage.setAttribute("label", this._stringBundle.getString("final-verify.title"));
  292.       path.value = "verify";
  293.     }
  294.     else if (type == "create") {
  295.       dataPage.setAttribute("label", this._stringBundle.getString("data-create.title"));
  296.       finalPage.setAttribute("label", this._stringBundle.getString("final-create.title"));
  297.       path.value = "create";
  298.     }
  299.   },
  300.  
  301.   /* advanceTo() - Called by buttons on account type screen.
  302.    *  Advances to the specified page.
  303.    */
  304.   advanceTo: function SyncWizard_advanceTo(pageid) {
  305.     let wizard = document.getElementById('sync-wizard');
  306.     wizard.canAdvance = true;
  307.     wizard.advance(pageid);
  308.   },
  309.  
  310.  
  311.   /////ACCOUNT VERIFICATION/////
  312.  
  313.   /* checkVerificationFields() - Called oninput from all fields, and onadvance from verification page
  314.    *  Checks that all fields have values and that the login and passphrase were verified
  315.    */
  316.   checkVerificationFields: function SyncWizard_checkVerify() {
  317.     let wizard = document.getElementById('sync-wizard');
  318.  
  319.     let statusLabel = document.getElementById('verify-account-error');
  320.     let username    = document.getElementById('sync-username-field').value;
  321.     let password    = document.getElementById('sync-password-field').value;
  322.     let passphrase  = document.getElementById('sync-passphrase-field').value;
  323.  
  324.     let loginVerified = this._stringBundle.getString("verify-success.label");
  325.  
  326.     wizard.canAdvance = false;
  327.  
  328.     if (!(username && password && passphrase)) {
  329.       wizard.canAdvance = false;
  330.       return false;
  331.     }
  332.  
  333.     // Make sure the login has been verified
  334.     // user could quickly enter an incorrect password and advance if malicious:)
  335.     // to prevent this, add a call to Weave.Service.login(), but this is redundant for now
  336.     if (document.getElementById('login-verified').value == "true" &&
  337.         document.getElementById('passphrase-verified').value == "true") {
  338.       wizard.canAdvance = true;
  339.       document.getElementById('verify-check').value = "true";
  340.       return true;
  341.     }
  342.  
  343.     wizard.canAdvance = false;
  344.     document.getElementById('verify-check').value = "false";
  345.     return false;
  346.   },
  347.  
  348.   /* verifyLogin() - Called when username or password field is changed.
  349.    *  Asychronously tests the login on the server.
  350.    */
  351.   verifyLogin: function SyncWizard_verifyLogin() {
  352.     let log = this._log;
  353.     let wizard = document.getElementById("sync-wizard");
  354.     let statusLabel = document.getElementById("verify-account-error");
  355.     let statusLink  = document.getElementById("verify-account-error-link");
  356.     let statusIcon  = document.getElementById("verify-account-icon");
  357.  
  358.     let username = document.getElementById("sync-username-field").value;
  359.     let password = document.getElementById("sync-password-field").value;
  360.  
  361.     let progress = this._stringBundle.getString("verify-progress.label");
  362.  
  363.     let loginVerified = document.getElementById("login-verified");
  364.  
  365.     // Don't allow advancing until we verify the account.
  366.     wizard.canAdvance = false;
  367.     document.getElementById("login-verified").value = "false";
  368.  
  369.     // Check for empty username or password fields
  370.     if (!username || !password) {
  371.       statusIcon.hidden = true;
  372.       statusLabel.value = "";
  373.       return;
  374.     }
  375.  
  376.     // Ok to verify, set the status and throbber
  377.     statusIcon.hidden  = false;
  378.     statusLink.hidden  = true;
  379.     statusLabel.hidden = false;
  380.     statusLabel.value  = progress;
  381.     statusLabel.style.color = PROGRESS_COLOR;
  382.  
  383.     // The observer will handle success and failure notifications
  384.     // checkVerificationFields() will take care of allowing advance if this works
  385.     log.info("Verifying username/password...");
  386.     Weave.Service.verifyLogin(null, username, password);
  387.  
  388.     // In case the server is hanging...
  389.     setTimeout(function() {
  390.             if (loginVerified.value == "false") {
  391.               log.info("Server timeout (username/password verification)");
  392.           statusIcon.hidden = true;
  393.           statusLabel.value = this._stringBundle.getString("serverTimeoutError.label");
  394.           statusLabel.style.color = SERVER_ERROR_COLOR;
  395.             }
  396.       }, SERVER_TIMEOUT);
  397.   },
  398.  
  399.   /* verifyPassphrase() - Called when passphrase field changes.
  400.    * Eventually this should actually verify that the passphrase works. :-)
  401.    */
  402.   verifyPassphrase : function SyncWizard_verifyPassphrase() {
  403.     let log = this._log;
  404.     let wizard = document.getElementById("sync-wizard");
  405.     let statusLabel = document.getElementById("verify-passphrase-error");
  406.     let statusLink  = document.getElementById("verify-passphrase-error-link");
  407.     let statusIcon  = document.getElementById("verify-passphrase-icon");
  408.  
  409.     let username = document.getElementById("sync-username-field").value;
  410.     let password = document.getElementById("sync-password-field").value;
  411.     let passphrase = document.getElementById("sync-passphrase-field").value;
  412.  
  413.     let progress = this._stringBundle.getString("passphrase-progress.label");
  414.  
  415.     let passphraseVerified = document.getElementById("passphrase-verified");
  416.  
  417.     // Don't allow advancing until we verify the account.
  418.     wizard.canAdvance = false;
  419.     document.getElementById("passphrase-verified").value = "false";
  420.  
  421.     // Check for empty passphrase field
  422.     if (!passphrase) {
  423.       statusIcon.hidden = true;
  424.       statusLabel.value = "";
  425.       return;
  426.     }
  427.  
  428.     // Ok to verify, set the status and throbber
  429.     statusIcon.hidden  = false;
  430.     statusLink.hidden  = true;
  431.     statusLabel.hidden = false;
  432.     statusLabel.value  = progress;
  433.     statusLabel.style.color = PROGRESS_COLOR;
  434.  
  435.     // The observer will handle success and failure notifications
  436.     // checkVerificationFields() will take care of allowing advance if this works
  437.     log.info("Verifying passphrase...");
  438.     Weave.Service.verifyPassphrase(null, username, password, passphrase);
  439.  
  440.     // In case the server is hanging...
  441.     let stringBundle = this._stringBundle;
  442.     setTimeout(function() {
  443.             if (statusLabel.value == progress) {
  444.                   log.info("Server timeout (passphrase verification)");
  445.               statusIcon.hidden = true;
  446.                       statusLabel.value = stringBundle.getString("serverTimeoutError.label");
  447.               statusLabel.style.color = SERVER_ERROR_COLOR;
  448.             }
  449.       }, SERVER_TIMEOUT);
  450.   },
  451.  
  452.   /* acceptExistingAccount() - Sets Weave properties so they are stored in login manager
  453.    *  Do not call until final wizard screen in case the user cancels setup.
  454.    */
  455.   acceptExistingAccount: function SyncWizard_acceptExistingAccount() {
  456.     let path = document.getElementById('path').value;
  457.     let username, password, passphrase;
  458.  
  459.     if (path == "verify") {
  460.       username = document.getElementById('sync-username-field').value;
  461.       password = document.getElementById('sync-password-field').value;
  462.       passphrase = document.getElementById('sync-passphrase-field').value;
  463.     }
  464.     else if (path == "create") {
  465.       username = document.getElementById('sync-username-create-field').value;
  466.       password = document.getElementById('sync-password-create-field').value;
  467.       passphrase = document.getElementById('sync-passphrase-create-field').value;
  468.     }
  469.  
  470.     // Setting these properties (really getters) results in this data being
  471.     // saved in the Firefox login manager.
  472.     this._log.info("Saving username, password, passphrase in login manager");
  473.     Weave.Service.username = username;
  474.     Weave.Service.password = password;
  475.     Weave.Service.passphrase = passphrase;
  476.  
  477.     return true;
  478.   },
  479.  
  480.   /* checkRegistrationStatus() - Called on Wizard load to see if registration is closed.
  481.    *   Sets boolean on gSyncWizard.registrationClosed.
  482.    */
  483.   checkRegistrationStatus: function SyncWizard_checkRegistrationStatus() {
  484.  
  485.     let log = this._log;
  486.     let httpRequest = new XMLHttpRequest();
  487.     let url = this._serverURL + REGISTER_STATUS;
  488.  
  489.     log.info("Checking registration status: " + url);
  490.  
  491.     httpRequest.open('GET', url, true);
  492.     httpRequest.onreadystatechange = function() {
  493.       if (httpRequest.readyState == 4) {
  494.         if (httpRequest.status == 200) {
  495.           if (httpRequest.responseText == 0) {
  496.             log.info("Registration closed");
  497.             gSyncWizard.registrationClosed = true;
  498.           } else {
  499.             log.info("Registration open");
  500.             gSyncWizard.registrationClosed = false;
  501.           }
  502.         } else {
  503.           log.info("checkRegistrationStatus error: received httpRequest.status " + httpRequest.status);
  504.         }
  505.       }
  506.     };
  507.     httpRequest.send(null);
  508.   },
  509.  
  510.   /////ACCOUNT CREATION - USERNAME, PASSWORD, PASSPHRASE/////
  511.  
  512.   /* checkUsername() - Called oncommand from username field for account creation.
  513.    *   Checks username availability.
  514.    */
  515.   checkUsername: function SyncWizard_checkUsername() {
  516.  
  517.     let wizard = document.getElementById('sync-wizard');
  518.     let username    = document.getElementById('sync-username-create-field').value;
  519.     let statusLabel = document.getElementById('create-username-error');
  520.     let statusLink  = document.getElementById('create-username-error-link');
  521.     let statusIcon  = document.getElementById('create-username-icon');
  522.  
  523.     let log = this._log;
  524.     let httpRequest = new XMLHttpRequest();
  525.     let url = this._serverURL + CHECK_USERNAME_URL + username;
  526.  
  527.     // Status messages
  528.     let usernameTaken      = this._stringBundle.getFormattedString("createUsername-error.label", [username]);
  529.     let usernameAvailable  = this._stringBundle.getFormattedString("createUsername-success.label", [username]);
  530.     let checkingUsername   = this._stringBundle.getString("createUsername-progress.label");
  531.     let serverError        = this._stringBundle.getString("serverError.label");
  532.     let serverTimeoutError = this._stringBundle.getString("serverTimeoutError.label");
  533.  
  534.     // Don't check if they haven't entered something
  535.     if (!username) {
  536.       statusIcon.hidden = true;
  537.       statusLink.hidden = true;
  538.       statusLabel.value = "";
  539.       wizard.canAdvance = false;
  540.       return false;
  541.     }
  542.  
  543.     // Show progress
  544.     statusIcon.hidden = false;
  545.     statusLink.hidden = true;
  546.     statusLabel.hidden = false;
  547.     statusLabel.value = checkingUsername;
  548.     statusLabel.style.color = PROGRESS_COLOR;
  549.  
  550.     // Check availability
  551.     httpRequest.open('GET', url, true);
  552.     httpRequest.onreadystatechange = function() {
  553.       if (httpRequest.readyState == 4) {
  554.         if (httpRequest.status == 200) {
  555.           statusIcon.hidden = true;
  556.           statusLink.hidden = true;
  557.  
  558.           if (httpRequest.responseText == 0) {
  559.             statusLabel.value = usernameTaken;
  560.             statusLabel.style.color = ERROR_COLOR;
  561.             wizard.canAdvance = false;
  562.             document.getElementById('create1-check').value = "false";
  563.             document.getElementById("username-verified").value = "false";
  564.           }
  565.           else {
  566.             statusLabel.value = usernameAvailable;
  567.             statusLabel.style.color = SUCCESS_COLOR;
  568.             document.getElementById("username-verified").value = "true";
  569.           }
  570.         }
  571.         else {
  572.           log.info("Error: received status " + httpRequest.status);
  573.           statusIcon.hidden = true;
  574.           statusLink.hidden = false;
  575.           // TODO: add more descriptive server errors in this case, we know what the status was
  576.           statusLabel.value = serverError;
  577.           statusLabel.style.color = SERVER_ERROR_COLOR;
  578.           wizard.canAdvance = false;
  579.           document.getElementById("username-verified").value = "false";
  580.           document.getElementById('create1-check').value = "false";
  581.         }
  582.       } };
  583.     httpRequest.send(null);
  584.  
  585.     // In case the server is hanging...
  586.     setTimeout(function() {
  587.             if (statusLabel.value == checkingUsername) {
  588.               this._log.info("Server timeout (username check)");
  589.               statusIcon.hidden = true;
  590.               statusLink.hidden = false;
  591.               statusLabel.value = serverTimeoutError;
  592.               statusLabel.style.color = SERVER_ERROR;
  593.             }
  594.       }, SERVER_TIMEOUT);
  595.   },
  596.  
  597.   /* checkEmail() - Called oncommand from email field in account creation.
  598.    *  Checks validity and availability of email address.
  599.    */
  600.   checkEmail: function SyncWizard_checkEmail() {
  601.  
  602.     let wizard = document.getElementById('sync-wizard');
  603.     let email       = document.getElementById('sync-email-create-field').value;
  604.     let statusLabel = document.getElementById('email-error');
  605.     let statusLink  = document.getElementById('email-error-link');
  606.     let statusIcon  = document.getElementById('email-icon');
  607.  
  608.     let log = this._log;
  609.     let httpRequest = new XMLHttpRequest();
  610.     let url = this._serverURL + CHECK_EMAIL_URL + email;
  611.     let regex = /^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,4}$/;
  612.  
  613.     // Status messages
  614.     let checkingEmail      = this._stringBundle.getString("email-progress.label");
  615.     let emailTaken         = this._stringBundle.getFormattedString("email-unavailable.label", [email]);
  616.     let emailOk            = this._stringBundle.getFormattedString("email-success.label", [email]);
  617.     let emailInvalid       = this._stringBundle.getString("email-invalid.label");
  618.     let serverError        = this._stringBundle.getString("serverError.label");
  619.     let serverTimeoutError = this._stringBundle.getString("serverTimeoutError.label");
  620.  
  621.     // Don't check if they haven't entered anything
  622.     if (!email) {
  623.       statusIcon.hidden = true;
  624.       statusLink.hidden = true;
  625.       statusLabel.value = "";
  626.       document.getElementById("email-verified").value = "false";
  627.       wizard.canAdvance = false;
  628.       return false;
  629.     }
  630.  
  631.     if (!regex.test(email)) {
  632.       statusIcon.hidden = true;
  633.       statusLink.hidden = true;
  634.       statusLabel.value = emailInvalid;
  635.       statusLabel.style.color = ERROR_COLOR;
  636.       document.getElementById("email-verified").value = "false";
  637.       wizard.canAdvance = false;
  638.       return false;
  639.     }
  640.  
  641.     // Show progress...
  642.     statusIcon.hidden = false;
  643.     statusLink.hidden = true;
  644.     statusLabel.value = checkingEmail;
  645.     statusLabel.style.color = PROGRESS_COLOR;
  646.  
  647.     httpRequest.open('GET', url, true);
  648.     httpRequest.onreadystatechange = function() {
  649.       if (httpRequest.readyState == 4) {
  650.         if (httpRequest.status == 200) {
  651.           statusIcon.hidden = true;
  652.           statusLink.hidden = true;
  653.           if (httpRequest.responseText == 0) {
  654.             statusLabel.value = emailTaken;
  655.             statusLabel.style.color = ERROR_COLOR;
  656.             wizard.canAdvance = false;
  657.             document.getElementById("email-verified").value = "false";
  658.           }
  659.           else {
  660.             statusLabel.value = emailOk;
  661.             statusLabel.style.color = SUCCESS_COLOR;
  662.             document.getElementById("email-verified").value = "true";
  663.           }
  664.         }
  665.         else {
  666.           log.info("Error: received status " + httpRequest.status);
  667.           statusIcon.hidden = true;
  668.           statusLink.hidden = false;
  669.           statusLabel.value = serverError;
  670.           statusLabel.style.color = SERVER_ERROR_COLOR;
  671.         }
  672.       }};
  673.     httpRequest.send(null);
  674.  
  675.     // If the server is hanging...
  676.     setTimeout(function() {
  677.             if (document.getElementById("email-verified").value == "false") {
  678.               this._log.info("Server timeout (email verification)");
  679.               statusIcon.hidden = true;
  680.               statusLink.hidden = false;
  681.               statusLabel.value = serverTimeoutError;
  682.               statusLabel.style.color = SERVER_ERROR_COLOR;
  683.               }
  684.       }, SERVER_TIMEOUT);
  685.  
  686.   },
  687.  
  688.  
  689.   /* checkAccountInput() - Called oncommand from password and passphrase entry/reentry fields.
  690.    *  Checks that password and passphrase reentry fields are the same, and that password
  691.    *  and passphrase are different values.
  692.    */
  693.   checkAccountInput: function SyncWizard_checkAccountInput(field) {
  694.     let wizard = document.getElementById('sync-wizard');
  695.     let username    = document.getElementById("sync-username-create-field").value;
  696.     let password1   = document.getElementById("sync-password-create-field").value;
  697.     let password2   = document.getElementById("sync-reenter-password-field").value;
  698.     let passphrase1 = document.getElementById("sync-passphrase-create-field").value;
  699.     let passphrase2 = document.getElementById("sync-reenter-passphrase-field").value;
  700.  
  701.     if (field == "password") {
  702.       let passwordMatchError = document.getElementById("password-match-error");
  703.  
  704.       // if the second password hasn't been entered yet, don't check
  705.       if (!password2) {
  706.         document.getElementById("password-verified").value = "false";
  707.         return false;
  708.       }
  709.  
  710.       // check that the two passwords are the same
  711.       if (password1 != password2)  {
  712.         passwordMatchError.value = this._stringBundle.getString("passwordsUnmatched.label");
  713.         passwordMatchError.style.color = ERROR_COLOR;
  714.         wizard.canAdvance = false;
  715.         document.getElementById("password-verified").value = "false";
  716.         return false;
  717.       }
  718.  
  719.       document.getElementById("password-verified").value = "true";
  720.       passwordMatchError.value = "";
  721.     }
  722.     else if (field == "passphrase") {
  723.       let passphraseError = document.getElementById("passphrase-match-error");
  724.  
  725.       // If the second passphrase hasn't been entered yet, don't check
  726.       if (!passphrase2) {
  727.         document.getElementById("passphrase-verified").value = "false";
  728.         return false;
  729.       }
  730.  
  731.       // check that the two passphrases are the same
  732.       if (passphrase1 != passphrase2)  {
  733.         passphraseError.value = this._stringBundle.getString("passphrasesUnmatched.label");
  734.         passphraseError.style.color = ERROR_COLOR;
  735.         wizard.canAdvance = false;
  736.         document.getElementById("passphrase-verified").value = "false";
  737.         return false;
  738.       }
  739.  
  740.       // check that they haven't entered the same password and passphrase
  741.       // TODO: check for this in the password case as well for the devious user case
  742.       if (passphrase1 == password1) {
  743.         passphraseError.value = this._stringBundle.getString("samePasswordAndPassphrase.label");
  744.         passphraseError.style.color = ERROR_COLOR;
  745.         wizard.canAdvance = false;
  746.         document.getElementById("passphrase-verified").value = "false";
  747.         return false;
  748.       }
  749.  
  750.       document.getElementById("passphrase-verified").value = "true";
  751.       passphraseError.value = "";
  752.     }
  753.     wizard.canAdvance = true;
  754.     return true;
  755.   },
  756.  
  757.  
  758.   /* checkCreationFields() - Called oninput from password entry fields.
  759.    *  Allows the wizard to continue if password fields have values and if an
  760.    *  available username has been chosen.
  761.    */
  762.   checkCreationFields: function SyncWizard_checkUserPasswordFields() {
  763.     let wizard = document.getElementById("sync-wizard");
  764.  
  765.     let username  = document.getElementById("sync-username-create-field").value;
  766.     let password1 = document.getElementById("sync-password-create-field").value;
  767.     let password2 = document.getElementById("sync-reenter-password-field").value;
  768.     let email     = document.getElementById("sync-email-create-field").value;
  769.  
  770.     // check for empty fields
  771.     if (!(username && password1 && password2 && email)) {
  772.       wizard.canAdvance = false;
  773.       return false;
  774.     }
  775.  
  776.     // check that everything has been verified
  777.     if (document.getElementById("username-verified").value == "true" &&
  778.         document.getElementById("email-verified").value == "true" &&
  779.         document.getElementById("password-verified").value == "true") {
  780.       wizard.canAdvance = true;
  781.       document.getElementById("create1-check").value = "true";
  782.       return true;
  783.     }
  784.  
  785.     wizard.canAdvance = false;
  786.     document.getElementById("create1-check").value = "false";
  787.     return false;
  788.   },
  789.  
  790.   /* checkPassphraseFields() - Called oninput from fields on passphrase / email entry screen.
  791.    *  Allows wizard to advance if all fields have a value.
  792.    */
  793.   checkPassphraseFields: function SyncWizard_checkPassphraseFields() {
  794.     let wizard = document.getElementById('sync-wizard');
  795.  
  796.     let passphrase1 = document.getElementById('sync-passphrase-create-field').value;
  797.     let passphrase2 = document.getElementById('sync-reenter-passphrase-field').value;
  798.  
  799.     // check for empty fields
  800.     if (!(passphrase1 && passphrase2)) {
  801.       wizard.canAdvance = false;
  802.       return false;
  803.     }
  804.  
  805.     // check that everything has been verified
  806.     if (document.getElementById("passphrase-verified").value == "true") {
  807.       wizard.canAdvance = true;
  808.       document.getElementById("create2-check").value = "true";
  809.       return true;
  810.     }
  811.  
  812.     wizard.canAdvance = false;
  813.     document.getElementById('create2-check').value = "false";
  814.     return false;
  815.   },
  816.  
  817.  
  818.  
  819.  
  820.   /* reloadCaptcha() - Called onclick from "try another image" link.
  821.    *  Refreshes captcha image.
  822.    */
  823.   reloadCaptcha: function SyncWizard_reloadCaptcha() {
  824.     document.getElementById("captcha").reload();
  825.   },
  826.  
  827.   onLoadCaptcha: function SyncWizard_onLoadCaptcha() {
  828.     let captchaImage = document.getElementById('captcha').contentDocument.getElementById('recaptcha_challenge_field').value;
  829.     document.getElementById('lastCaptchaChallenge').value = captchaImage;
  830.     document.getElementById('captchaImage').setAttribute("src", CAPTCHA_IMAGE_URL + "?c=" + captchaImage);
  831.   },
  832.  
  833.  
  834.   /* createAccount() - Called onadvance for final account creation screen.
  835.    *  Posts http request to server, and checks for correct captcha response.
  836.    */
  837.  
  838.   createAccount: function SyncWizard_createAccount() {
  839.  
  840.     let wizard = document.getElementById('sync-wizard');
  841.     let statusLabel = document.getElementById('account-creation-status');
  842.     let statusLink  = document.getElementById('account-creation-status-link');
  843.     let statusIcon  = document.getElementById('account-creation-status-icon');
  844.  
  845.     let captchaError   = document.getElementById('captcha-error');
  846.     let captchaImage   = document.getElementById('captcha').contentDocument.getElementById('recaptcha_challenge_field').value;
  847.  
  848.     let username         = document.getElementById('sync-username-create-field').value;
  849.     let created          = this._stringBundle.getFormattedString("create-success.label", [username]);
  850.     let serverError      = this._stringBundle.getString("serverError.label");
  851.     let progress         = this._stringBundle.getString("create-progress.label");
  852.     let uidTaken         = this._stringBundle.getString("create-uid-inuse.label");
  853.     let uidMissing       = this._stringBundle.getString("create-uid-missing.label");
  854.     let uidInvalid       = this._stringBundle.getString("create-uid-invalid.label");
  855.     let emailInvalid     = this._stringBundle.getString("create-mail-invalid.label");
  856.     let emailTaken       = this._stringBundle.getString("create-mail-inuse.label");
  857.     let captchaMissing   = this._stringBundle.getString("create-captcha-missing.label");
  858.     let passwordMissing  = this._stringBundle.getString("create-password-missing.label");
  859.     let incorrectCaptcha = this._stringBundle.getString("incorrectCaptcha.label");
  860.  
  861.  
  862.     let log = this._log;
  863.     let httpRequest = new XMLHttpRequest();
  864.  
  865.     if (document.getElementById("create3-check").value == "true")
  866.       return true;
  867.  
  868.     // tell the user the server is working...
  869.     statusIcon.hidden = false;
  870.     statusLink.hidden = true;
  871.     statusLabel.hidden = false;
  872.     statusLabel.value = progress;
  873.     statusLabel.style.color = PROGRESS_COLOR;
  874.  
  875.     // hide the captcha error message in case that was the problem
  876.     captchaError.value = "";
  877.  
  878.     httpRequest.open('POST', this._serverURL + REGISTER_URL, true);
  879.  
  880.     httpRequest.onreadystatechange = function() {
  881.     if (httpRequest.readyState == 4) {
  882.       switch (httpRequest.status) {
  883.  
  884.      // CREATED
  885.         case 201:
  886.           captchaError.value = "";
  887.           if (httpRequest.responseText == "2: VERIFICATION SENT")
  888.             log.info("Account created, verification email sent.");
  889.           else if (httpRequest.responseText == "3: CREATED")
  890.             log.info("Account created, no email address given.");
  891.  
  892.           //document.getElementById('lastCaptchaChallenge').value = captchaImage;
  893.  
  894.           statusIcon.hidden = true;
  895.           statusLink.hidden = true;
  896.           statusLabel.value = created;
  897.           statusLabel.style.color = SUCCESS_COLOR;
  898.  
  899.           document.getElementById("create3-check").value = "true";
  900.           wizard.canAdvance = true;
  901.           wizard.advance('sync-wizard-data');
  902.           break;
  903.  
  904.         // BAD REQUEST (the user should rarely get to this state -> ok to report one at a time)
  905.         case 400:
  906.           statusIcon.hidden = true;
  907.           statusLink.hidden = true;
  908.           statusLabel.style.color = ERROR_COLOR;
  909.           let response = httpRequest.responseText;
  910.           log.info("Status 400: Account not created, response " + response);
  911.           if (response.match("0") && !response.match("-10"))
  912.             statusLabel.value = uidTaken;
  913.           else if (response.match("-2"))
  914.             statusLabel.value = uidMissing;
  915.           else if (response.match("-3"))
  916.             statusLabel.value = uidInvalid;
  917.           else if (response.match("-4"))
  918.             statusLabel.value = emailInvalid;
  919.           else if (response.match("-5"))
  920.             statusLabel.value = emailTaken;
  921.           else if (response.match("-7")) {
  922.             captchaError.value = captchaMissing;
  923.             captchaError.style.color = ERROR_COLOR;
  924.             statusLabel.hidden = true;
  925.           }
  926.           else if (response.match("-8"))
  927.             statusLabel.value = passwordMissing;
  928.           else
  929.             statusLabel.value = serverError;
  930.  
  931.           document.getElementById("create3-check").value = "false";
  932.           wizard.canAdvance = false;
  933.           break;
  934.  
  935.         // CAPTCHA FAILED
  936.         case 417:
  937.           log.info("Incorrect Captcha response. Account not created.");
  938.           captchaError.value = incorrectCaptcha;
  939.           captchaError.style.color = ERROR_COLOR;
  940.           document.getElementById('captcha').reload();
  941.           document.getElementById('captchaInput').value = "";
  942.           statusIcon.hidden = true;
  943.           statusLink.hidden = true;
  944.           statusLabel.hidden = true;
  945.           document.getElementById("create3-check").value = "false";
  946.           wizard.canAdvance = false;
  947.           break;
  948.  
  949.         default:
  950.           log.info("Error: received status " + httpRequest.status + ". Account not created.");
  951.           statusIcon.hidden = true;
  952.           statusLink.hidden = false;
  953.           statusLabel.value = serverError;
  954.           statusLabel.style.color = SERVER_ERROR_COLOR;
  955.  
  956.           document.getElementById("create3-check").value = "false";
  957.           wizard.canAdvance = false;
  958.           break;
  959.         }
  960.       }
  961.     };
  962.  
  963.     let uid = document.getElementById("sync-username-create-field").value;
  964.     let password = document.getElementById("sync-password-create-field").value;
  965.     let passphrase = document.getElementById("sync-passphrase-create-field").value;
  966.     let mail = document.getElementById("sync-email-create-field").value;
  967.  
  968.     let captchaDoc = document.getElementById("captcha").contentDocument;
  969.     let challenge = document.getElementById("lastCaptchaChallenge").value;
  970.     let response = document.getElementById("captchaInput").value;
  971.  
  972.     let message = "uid=" + encodeURIComponent(uid) +
  973.       "&password=" + encodeURIComponent(password) +
  974.       "&mail=" + encodeURIComponent(mail) +
  975.       "&recaptcha_response_field=" + encodeURIComponent(response) +
  976.       "&recaptcha_challenge_field=" + encodeURIComponent(challenge) +
  977.       "&token=3419b5893291d055";
  978.  
  979.     httpRequest.setRequestHeader("Content-Type", "application/x-www-form-urlencoded");
  980.     httpRequest.setRequestHeader("Content-Length", message.length);
  981.     httpRequest.send(message);
  982.  
  983.     // in case the server is hanging...
  984.     setTimeout(function() {
  985.       if (document.getElementById("create3-check").value == "false") {
  986.         this._log.info("Server timeout (account creation)");
  987.         statusIcon.hidden = true;
  988.         statusLink.hidden = false;
  989.         statusLabel.value = serverTimeoutError;
  990.         statusLabel.style.color = SERVER_ERROR_COLOR;
  991.       }
  992.     }, SERVER_TIMEOUT);
  993.  
  994.     return false;
  995.   },
  996.  
  997.  
  998.  
  999.   /////INSTALLATION, FINAL SYNC/////
  1000.  
  1001.   /* checkFinalFields() - Called oninput from fields on final account creation screen.
  1002.    *  Allows wizard to advance if all fields have a value.
  1003.    */
  1004.   checkFinalFields: function SyncWizard_checkFinalFields() {
  1005.     let wizard = document.getElementById('sync-wizard');
  1006.  
  1007.     let input = document.getElementById('captchaInput').value;
  1008.     let agree = document.getElementById('terms-checkbox');
  1009.  
  1010.     if (!input || !agree.checked) {
  1011.       wizard.canAdvance = false;
  1012.       return false;
  1013.     }
  1014.  
  1015.     wizard.canAdvance = true;
  1016.     return true;
  1017.   },
  1018.  
  1019.  
  1020.   /* completeInstallation() - Called on advance from final wizard screen.
  1021.    *  Sets prefs, does final login, does an initial sync.
  1022.    */
  1023.   completeInstallation: function SyncWizard_completeInstallation() {
  1024.     let wizard        = document.getElementById("sync-wizard");
  1025.     let prefStatus    = document.getElementById("final-pref-status");
  1026.     let accountStatus = document.getElementById("final-account-status");
  1027.     let syncStatus    = document.getElementById("final-sync-status");
  1028.     let finalStatus   = document.getElementById("final-status");
  1029.     let finalLink     = document.getElementById("final-status-link");
  1030.     let finalIcon     = document.getElementById("final-status-icon");
  1031.     let prefsProgress = this._stringBundle.getString("initialPrefs-progress.label");
  1032.     let loginProgress = this._stringBundle.getString("initialLogin-progress.label");
  1033.     let syncProgress  = this._stringBundle.getString("initialSync-progress.label");
  1034.     let loginError    = this._stringBundle.getString("initialLogin-error.label");
  1035.     let syncError     = this._stringBundle.getString("initialSync-error.label");
  1036.  
  1037.  
  1038.     // don't do anything if the sync has already happened
  1039.     if (document.getElementById("sync-success").value == "true")
  1040.       return true;
  1041.  
  1042.     // don't let them continue once continue has been clicked once
  1043.     if (document.getElementById("installation-started").value == "true")
  1044.       return false;
  1045.  
  1046.     // now set the value for the first time through
  1047.     document.getElementById("installation-started").value = "true";
  1048.     wizard.canAdvance = false;
  1049.  
  1050.  
  1051.     finalStatus.style.color = PROGRESS_COLOR;
  1052.     finalIcon.hidden = false;
  1053.     finalLink.hidden = true;
  1054.  
  1055.     // for server error case, only start at sync if login worked
  1056.     if (Weave.Service.isInitialized) {
  1057.       gSyncWizard.initialSync();
  1058.       return;
  1059.     }
  1060.  
  1061.     // set prefs
  1062.     finalStatus.value = prefsProgress;
  1063.     gSyncWizard.setPrefs();
  1064.     prefStatus.style.color = SUCCESS_COLOR;
  1065.  
  1066.     // login and perform initial sync
  1067.     finalStatus.value = loginProgress;
  1068.     finalIcon.hidden = false;
  1069.  
  1070.     // adds username and password to manager
  1071.     gSyncWizard.acceptExistingAccount();
  1072.  
  1073.     // login using those values
  1074.     Weave.Service.loginAndInit(function() {
  1075.           if(Weave.Service.isInitialized) {
  1076.             accountStatus.style.color = SUCCESS_COLOR;
  1077.             gSyncWizard.initialSync();
  1078.           }
  1079.           else {
  1080.             accountStatus.style.color = ERROR_COLOR;
  1081.             finalStatus.value = loginError;
  1082.             finalStatus.style.color = SERVER_ERROR_COLOR;
  1083.             finalIcon.hidden = true;
  1084.             finalLink.hidden = false;
  1085.           }
  1086.       });
  1087.  
  1088.     // don't let them advance- only sync:success will advance
  1089.     return false;
  1090.   },
  1091.  
  1092.   /* initialSync() - Called from completeInstallation().
  1093.    *  Sets page values and does a sync.
  1094.    */
  1095.   initialSync: function SyncWizard_initialSync() {
  1096.     let finalStatus   = document.getElementById('final-status');
  1097.     let finalLink     = document.getElementById('final-status-link');
  1098.     let finalIcon     = document.getElementById('final-status-icon');
  1099.     let syncProgress  = this._stringBundle.getString("initialSync-progress.label");
  1100.  
  1101.     finalStatus.value = syncProgress;
  1102.     finalIcon.hidden = false;
  1103.     finalLink.hidden = true;
  1104.  
  1105.     let wm = Cc["@mozilla.org/appshell/window-mediator;1"].
  1106.       getService(Ci.nsIWindowMediator);
  1107.     let window = wm.getMostRecentWindow("Sync:Status");
  1108.     if (window)
  1109.       window.focus();
  1110.      else {
  1111.        var ww = Cc["@mozilla.org/embedcomp/window-watcher;1"].
  1112.          getService(Ci.nsIWindowWatcher);
  1113.        let options = 'chrome,centerscreen,dialog,modal,resizable=yes';
  1114.        ww.activeWindow.openDialog("chrome://weave/content/status.xul", '', options, null);
  1115.      }
  1116.   },
  1117.  
  1118.   /* setPrefs() - Called during final screen checklist.
  1119.    *  Prefs are set on the previous screen, but committed here in case the user "Cancels".
  1120.    */
  1121.   setPrefs: function SyncWizard_setPrefs() {
  1122.  
  1123.     let branch = Cc["@mozilla.org/preferences-service;1"].
  1124.     getService(Ci.nsIPrefService).
  1125.     getBranch(Weave.PREFS_BRANCH + "engine.");
  1126.  
  1127.     let value;
  1128.  
  1129.     // TODO: Move this into a separate module for use in prefs and wizard
  1130.     value = document.getElementById('sync-wizard-bookmarks').checked;
  1131.     branch.setBoolPref("bookmarks", value);
  1132.     value = document.getElementById('sync-wizard-history').checked;
  1133.     branch.setBoolPref("history", value);
  1134.     value = document.getElementById('sync-wizard-cookies').checked;
  1135.     branch.setBoolPref("cookies", value);
  1136.     value = document.getElementById('sync-wizard-passwords').checked;
  1137.     branch.setBoolPref("passwords", value);
  1138.     value = document.getElementById('sync-wizard-tabs').checked;
  1139.     branch.setBoolPref("tabs", value);
  1140.     value = document.getElementById('sync-wizard-forms').checked;
  1141.     branch.setBoolPref("forms", value);
  1142.  
  1143.     this._log.info("Preferences set.");
  1144.  
  1145.     return true;
  1146.   },
  1147.  
  1148.  
  1149.   observe: function(subject, topic, data) {
  1150.     if (!document) {
  1151.       this._log.warn("XXX FIXME: wizard observer called after wizard went away");
  1152.       return;
  1153.     }
  1154.     let wizard = document.getElementById('sync-wizard');
  1155.  
  1156.     switch(topic) {
  1157.  
  1158.     case "weave:service:verify-login:success": {
  1159.       this._log.info("Login verify succeeded");
  1160.  
  1161.       document.getElementById('login-verified').value = "true";
  1162.  
  1163.       let statusIcon  = document.getElementById('verify-account-icon');
  1164.       let statusLink  = document.getElementById('verify-account-error-link');
  1165.       let statusLabel = document.getElementById('verify-account-error');
  1166.  
  1167.       statusIcon.hidden = true;
  1168.       statusLink.hidden = true;
  1169.       statusLabel.value = this._stringBundle.getString("verify-success.label");
  1170.       statusLabel.style.color = SUCCESS_COLOR;
  1171.  
  1172.       // If the passphrase hasn't been verified, try doing so now.
  1173.       // Its check may have been deferred until we had a valid login.
  1174.       if (document.getElementById('passphrase-verified').value == "false") {
  1175.         this._log.info("Checking passphrase after login verify");
  1176.         this.verifyPassphrase();
  1177.       }
  1178.  
  1179.       gSyncWizard.checkVerificationFields();
  1180.       // Don't allow the wizard to advance here in case other fields weren't filled in
  1181.       break;
  1182.     }
  1183.     case "weave:service:verify-passphrase:success": {
  1184.       this._log.info("Passphrase verify succeeded");
  1185.  
  1186.       document.getElementById('passphrase-verified').value = "true";
  1187.  
  1188.       let statusIcon  = document.getElementById('verify-passphrase-icon');
  1189.       let statusLink  = document.getElementById('verify-passphrase-error-link');
  1190.       let statusLabel = document.getElementById('verify-passphrase-error');
  1191.  
  1192.       statusIcon.hidden = true;
  1193.       statusLink.hidden = true;
  1194.       statusLabel.value = this._stringBundle.getString("passphrase-success.label");
  1195.       statusLabel.style.color = SUCCESS_COLOR;
  1196.  
  1197.       gSyncWizard.checkVerificationFields();
  1198.       // Don't allow the wizard to advance here in case other fields weren't filled in
  1199.       break;
  1200.     }
  1201.  
  1202.     case "weave:service:login:success":
  1203.       this._log.info("Initial login succeeded");
  1204.       break;
  1205.  
  1206.     case "weave:service:login:error":
  1207.       this._log.info("Initial login failed");
  1208.       break;
  1209.  
  1210.     case "weave:service:verify-login:error": {
  1211.       this._log.info("Login verify failed");
  1212.  
  1213.       document.getElementById('login-verified').value = "false";
  1214.  
  1215.       let statusIcon  = document.getElementById('verify-account-icon');
  1216.       let statusLink  = document.getElementById('verify-account-error-link');
  1217.       let statusLabel = document.getElementById('verify-account-error');
  1218.  
  1219.       statusIcon.hidden = true;
  1220.       statusLink.hidden = true;
  1221.       statusLabel.value = this._stringBundle.getString("verify-error.label");
  1222.       statusLabel.style.color = ERROR_COLOR;
  1223.  
  1224.       wizard.canAdvance = false;
  1225.       break;
  1226.     }
  1227.  
  1228.     case "weave:service:verify-passphrase:error": {
  1229.       this._log.info("Passphrase verify failed");
  1230.  
  1231.       document.getElementById('passphrase-verified').value = "false";
  1232.  
  1233.       let statusIcon  = document.getElementById('verify-passphrase-icon');
  1234.       let statusLink  = document.getElementById('verify-passphrase-error-link');
  1235.       let statusLabel = document.getElementById('verify-passphrase-error');
  1236.  
  1237.       statusIcon.hidden = true;
  1238.       statusLink.hidden = true;
  1239.       statusLabel.value = this._stringBundle.getString("passphrase-error.label");
  1240.       statusLabel.style.color = ERROR_COLOR;
  1241.  
  1242.       wizard.canAdvance = false;
  1243.       break;
  1244.     }
  1245.  
  1246.     case "weave:service:logout:success":
  1247.       this._log.info("Logged out");
  1248.       break;
  1249.  
  1250.     case "weave:service:sync:success": {
  1251.       let syncStatus    = document.getElementById('final-sync-status');
  1252.       let finalStatus   = document.getElementById('final-status');
  1253.       let finalLink     = document.getElementById('final-status-link');
  1254.       let finalIcon     = document.getElementById('final-status-icon');
  1255.       let syncProgress  = this._stringBundle.getString("initialSync-progress.label");
  1256.       let complete      = this._stringBundle.getString("installation-complete.label");
  1257.  
  1258.       this._log.info("Initial Sync performed");
  1259.       syncStatus.style.color = SUCCESS_COLOR;
  1260.       finalStatus.value = complete;
  1261.       finalIcon.hidden = true;
  1262.       finalLink.hidden = true;
  1263.  
  1264.       document.getElementById("sync-success").value = "true";
  1265.       wizard.canAdvance = true;
  1266.       wizard.advance('sync-wizard-thankyou');
  1267.       break;
  1268.     }
  1269.  
  1270.     case "weave:service:sync:error": {
  1271.       let syncStatus    = document.getElementById('final-sync-status');
  1272.       let finalStatus   = document.getElementById('final-status');
  1273.       let finalLink     = document.getElementById('final-status-link');
  1274.       let finalIcon     = document.getElementById('final-status-icon');
  1275.       let syncError     = this._stringBundle.getString("initialSync-error.label");
  1276.  
  1277.       this._log.info("Initial Sync failed");
  1278.       syncStatus.style.color = ERROR_COLOR;
  1279.       finalStatus.value = syncError;
  1280.       finalStatus.style.color = SERVER_ERROR_COLOR;
  1281.       finalLink.hidden = false;
  1282.       finalIcon.hidden = true;
  1283.  
  1284.       //this will allow them to run completeInstallation() again (try again)
  1285.       document.getElementById("installation-started").value = "false";
  1286.       break;
  1287.     }
  1288.  
  1289.     default:
  1290.       this._log.warn("Unknown observer notification topic: " + topic);
  1291.       break;
  1292.     }
  1293.   }
  1294. };
  1295.  
  1296. let gSyncWizard = new SyncWizard();
  1297.